home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Frameworks / MacZoop 1.6.5 / Basic Classes / Z Sources / ZDialog.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-21  |  36.8 KB  |  1,454 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            ObjectMacZapp        -- a standard Mac OOP application template
  5. *
  6. *
  7. *
  8. *            ZDialog.cpp            -- a dialog box
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include    "ZDialog.h"
  23. #include    "MacZoop.h"
  24. #include    "ZGrafState.h"
  25.  
  26. #include    <dialogs.h>
  27. #include    <palettes.h>
  28. #include    <fp.h>
  29.  
  30. // static method and global UPP to handle user items in dialogs in a general
  31. // object-oriented fashion. Hey- cool feature!
  32.  
  33. static pascal void    UserItemVectorProc(DialogPtr theDialog, short item);
  34. UserItemUPP    gUIVectorUPP = NewUserItemProc(UserItemVectorProc);
  35.  
  36. /*-------------------------------***  CONSTRUCTOR  ***----------------------------------*/
  37.  
  38.  
  39. ZDialog::ZDialog(ZCommander* aBoss, const short dialogID)
  40.     : ZWindow(aBoss, dialogID)
  41. {
  42.     isModal = FALSE;    // set up by MakeMacWindow
  43.     FailNIL( rGroupList = ( RGroupHdl ) NewHandle( 0 ));    // resized as needed
  44.     ictb = NULL;
  45.     signalDismiss = 0;
  46. }
  47.  
  48.  
  49. /*---------------------------------***  DESTRUCTOR  ***----------------------------------*/
  50.  
  51.  
  52. ZDialog::~ZDialog()
  53. {
  54.     if ( isModal )
  55.         gWindowManager->Activate();
  56.     
  57.     if ( macWindow )
  58.         DisposeDialog( macWindow );
  59.  
  60.     macWindow = NULL;
  61.     
  62.     if ( rGroupList )
  63.         DisposeHandle(( Handle ) rGroupList );
  64.         
  65.     if ( ictb )
  66.         DisposeHandle((Handle) ictb );
  67. }
  68.  
  69. /*-------------------------------***  INITZWINDOW  ***----------------------------------*/
  70. /*    
  71.  
  72. construct the dialog and set it up
  73.  
  74. ----------------------------------------------------------------------------------------*/
  75.  
  76. void    ZDialog::InitZWindow()
  77. {
  78.     MakeMacWindow( windID );    // make the dialog box, and set modal flag
  79.     
  80.     SetUpUserItems();            // install user item procs so we get callbacks
  81.     SetUpRadioGroups();            // automatically deal with radio button groups
  82.     SetUp();                    // call user's set up method
  83.     
  84.     // tell the window manager of our existence. This must be done after the
  85.     // full build of the mac window since the window manager needs to get
  86.     // information from it. Thus if you override this method, make sure you
  87.     // make the same call.
  88.     
  89.     gWindowManager->AddWindow( this );
  90. }
  91.  
  92.  
  93. /*------------------------------***  MAKEMACWINDOW  ***---------------------------------*/
  94. /*    
  95.  
  96. make a dialog. This tries to construct a dialog using a 'DLOG' resource with the ID
  97. passed. The refcon is set to this object, so do not use it. Sets the modal flag too.
  98.  
  99. ----------------------------------------------------------------------------------------*/
  100.  
  101. void    ZDialog::MakeMacWindow( const short dialogID )
  102. {
  103.     FailNIL( macWindow = GetNewDialog( dialogID, NULL, NULL ));
  104.     
  105.     // set our refcon to point to the object. DO NOT USE THE REFCON!
  106.     
  107.     SetWRefCon( macWindow, (long) this );
  108.     
  109.     // see whether this is modal or not by examining the style of the window. This
  110.     // flag affects the way commands are processed.
  111.     
  112.     short wVar = GetWVariant( macWindow );
  113.     
  114.     isModal = ( wVar == dBoxProc     ||
  115.                 wVar == plainDBox     ||
  116.                 wVar == altDBoxProc ||
  117.                 wVar == movableDBoxProc );
  118.     
  119.     // note that dialogs should normally not set the <isFloating> member, since the window
  120.     // manager knows that dialogs should go in front of floaters anyway. If you use a dialog as
  121.     // a floating window, note that it won't get the menubar and keyboard focus, so you should
  122.     // avoid the use of editable text fields, etc. Though no-one's enforcing any of this, it
  123.     // is bad human interface to have type-in fields in floating windows.
  124.     
  125.     // look for any associated 'ictb' resource and keep a local copy
  126.     
  127.     ictb = ( ictbHandle ) GetResource( 'ictb', dialogID );
  128.     
  129.     if ( ictb )
  130.     {
  131.         DetachResource((Handle) ictb );
  132.         HNoPurge((Handle) ictb );
  133.     }
  134. }
  135.  
  136.  
  137. /*-----------------------------***  SETUPUSERITEMS  ***---------------------------------*/
  138. /*    
  139.  
  140. make every user item point to our vector proc for handling these items. Then you can
  141. simply override DrawUserItem to draw anything you want in the dialog!
  142.  
  143. ----------------------------------------------------------------------------------------*/
  144.  
  145. void    ZDialog::SetUpUserItems()
  146. {
  147.     short    item, itemType;
  148.     Handle    itemHand;
  149.     Rect    itemBox;
  150.     
  151.     item = CountDITL( macWindow );
  152.     
  153.     while( item )
  154.     {
  155.         GetDialogItem( macWindow, item--, &itemType, &itemHand, &itemBox );
  156.         
  157.         if (( itemType & 0x7F ) == userItem )
  158.             SetDialogItem( macWindow, item + 1, itemType, (Handle) gUIVectorUPP, &itemBox );
  159.     }
  160. }
  161.  
  162.  
  163.  
  164. /*-----------------------------------***  DRAW  ***-------------------------------------*/
  165. /*    
  166. draws the dialog items
  167. ----------------------------------------------------------------------------------------*/
  168.  
  169. void    ZDialog::Draw()
  170. {
  171.     UpdateDialog( macWindow, macWindow->visRgn );
  172.  
  173.     if ( isModal )
  174.         OutlineDefaultItem();
  175.         
  176.     #ifdef _GREYSCALE_APPEARANCE
  177.     
  178.     AddGreyscaleEffects();
  179.     
  180.     
  181.     #endif    
  182. }
  183.  
  184.  
  185. /*-----------------------------------***  CLICK  ***------------------------------------*/
  186. /*    
  187. handle clicks in the dialog, This determines the item and calls ClickItem.
  188. ----------------------------------------------------------------------------------------*/
  189.  
  190. void    ZDialog::Click( const Point mouse, const short modifiers )
  191. {
  192.     DialogPeek    dp = ( DialogPeek ) macWindow;
  193.     
  194.     // which item was hit?
  195.     
  196.     short    item = FindDialogItem( macWindow, mouse ) + 1;
  197.     
  198.     // if the item is enabled, call TrackControl, TEClick, etc as needed.
  199.     
  200.     if ( item > 0 )
  201.     {
  202.         short    iType, partCode;
  203.         Handle    iHand;
  204.         Rect    iBox;
  205.         
  206.         GetDialogItem( macWindow, item, &iType, &iHand, &iBox );
  207.         
  208.         // if the item is a control, track it. Call ClickItem if control clicked and
  209.         // item was enabled and not unhilited.
  210.         
  211.         if (iType & ctrlItem )
  212.         {
  213.             if ((*(ControlHandle) iHand )->contrlHilite != 255 )
  214.             {
  215.                 partCode = TrackControl((ControlHandle) iHand, mouse, ( ControlActionUPP ) -1L );
  216.             
  217.                 if (( partCode != 0 ) && (( iType & 0x80 ) == 0 ))
  218.                     ClickItem( item );
  219.             }
  220.         }
  221.         else
  222.         {
  223.             if ( iType & editText )
  224.             {
  225.                 // if an edit field, pass click to text edit. If not in the current
  226.                 // field, switch fields to the one clicked.
  227.                 
  228.                 ZGrafState    zg;
  229.                 
  230.                 if ( item != dp->editField + 1)
  231.                     SelectDialogItemText( macWindow, item, 0, 0 );
  232.  
  233.                 SetTEItemDataFromIctb( item, TRUE );
  234.                 TEClick( mouse, (modifiers & shiftKey) == shiftKey , dp->textH );
  235.             }
  236.             
  237.             // all enabled items are passed to ClickItem
  238.             
  239.             if (( iType & 0x80 ) == 0 )
  240.                 ClickItem( item );
  241.         }
  242.     }
  243.     
  244.     // see if any user action resulted in a request to dismiss the dialog. This is quite common-
  245.     // e.g. a double-click in a list, etc. To close safely, we need to action this right at the end
  246.     // of processing a click. To work this, set signalDismiss to ok or cancel in response to your
  247.     // action- do not call Close directly or things may not work as you expect, or worse, crash.
  248.     
  249.     if ( signalDismiss > 0 )
  250.         FakeClick( signalDismiss );
  251. }
  252.  
  253.  
  254. /*---------------------------------***  ACTIVATE  ***-----------------------------------*/
  255. /*    
  256. activates TextEdit if present
  257. ----------------------------------------------------------------------------------------*/
  258.  
  259. void    ZDialog::Activate()
  260. {
  261.     DialogPeek    dp = (DialogPeek) macWindow;
  262.     
  263.     if ( HasEditFields())
  264.         TEActivate( dp->textH );
  265.     
  266.     inherited::Activate();
  267. }
  268.  
  269.  
  270. /*--------------------------------***  DEACTIVATE  ***----------------------------------*/
  271. /*    
  272. deactivates TextEdit if present
  273. ----------------------------------------------------------------------------------------*/
  274.  
  275. void    ZDialog::Deactivate()
  276. {
  277.     inherited::Deactivate();
  278.     
  279.     DialogPeek    dp = (DialogPeek) macWindow;
  280.     
  281.     if ( HasEditFields())
  282.         TEDeactivate( dp->textH );
  283. }
  284.  
  285.  
  286. /*-----------------------------------***  IDLE  ***-------------------------------------*/
  287. /*    
  288. blink TextEdit cursor if present
  289. ----------------------------------------------------------------------------------------*/
  290.  
  291. void    ZDialog::Idle()
  292. {
  293.     DialogPeek    dp = (DialogPeek) macWindow;
  294.     
  295.     if ( HasEditFields())
  296.         TEIdle( dp->textH );
  297. }
  298.  
  299.  
  300. /*-----------------------------------***  TYPE  ***-------------------------------------*/
  301. /*    
  302. pass TextEdit the typed character if present. If tab key, cycle through fields
  303. ----------------------------------------------------------------------------------------*/
  304.  
  305. void    ZDialog::Type( const char theKey )
  306. {
  307.     DialogPeek    dp = (DialogPeek) macWindow;
  308.     short        iType;
  309.     Handle        iHand;
  310.     Rect        iBox;
  311.     
  312.     Focus();
  313.     
  314.     if ( HasEditFields())
  315.     {
  316.         if ( theKey == TAB_KEY )        // tab
  317.         {
  318.             short    nextField, fMax;
  319.             
  320.             // find the next edit field item that can be set
  321.             
  322.             nextField = dp->editField + 2;
  323.             fMax = CountDITL( macWindow );
  324.             
  325.             do
  326.             {
  327.                 if ( nextField > fMax )
  328.                     nextField = 1;
  329.                 
  330.                 // if we got back to where we started, so nothing. This will occur
  331.                 // if the dialog has only 1 edit field
  332.                 
  333.                 if ( nextField == dp->editField + 1 )
  334.                     return;
  335.                 
  336.                 GetDialogItem( macWindow, nextField, &iType, &iHand, &iBox );
  337.                 
  338.                 // if this is an edit field, then select that one
  339.                 
  340.                 if ( iType & editText )
  341.                 {
  342.                     SelectDialogItemText( macWindow, nextField, 0, 32767 );
  343.                     SetTEItemDataFromIctb( nextField, FALSE );
  344.                     break;    
  345.                 }
  346.                 
  347.                 nextField++;
  348.             }
  349.             while( 1 );
  350.         }
  351.         else
  352.         {
  353.             if ( dp->textH )
  354.             {
  355.                 ZGrafState    zg;
  356.                     
  357.                 SetTEItemDataFromIctb( dp->editField + 1, TRUE );
  358.                 TEKey( theKey, dp->textH );
  359.             }
  360.         }
  361.         
  362.         ClipRect( &macWindow->portRect );
  363.         
  364.         // if item is enabled, call ClickItem too
  365.         
  366.         GetDialogItem( macWindow, dp->editField + 1, &iType, &iHand, &iBox );
  367.         
  368.         if (( iType & 0x80 ) == 0 )
  369.             ClickItem( dp->editField + 1 );
  370.     }
  371. }
  372.  
  373.  
  374.  
  375. /*------------------------------***  DRAWUSERITEM  ***----------------------------------*/
  376. /*    
  377.  
  378. this is called to update each user item in the dialog. You can override this to draw
  379. custom dialog items. The default method draws a 50% grey outline around the item.
  380.  
  381. ----------------------------------------------------------------------------------------*/
  382.  
  383. void    ZDialog::DrawUserItem( const short item )
  384. {
  385.     short    itemType;
  386.     Handle    itemHand;
  387.     Rect    itemBox;
  388.     
  389.     GetDialogItem( macWindow, item, &itemType, &itemHand, &itemBox );
  390.     
  391.     // if the background of the window is not white, and the compiler flag is
  392.     // set, draw a 3D effect line instead of a 50% gray one.
  393.     
  394.     #ifdef _GREYSCALE_APPEARANCE
  395.     
  396.     AuxWinHandle    awH;
  397.     
  398.     if ( GetAuxWin( macWindow, &awH ))
  399.     {
  400.         RGBColor    rc;
  401.         GDHandle    mDev;
  402.         Rect        gib;
  403.         
  404.         rc.red = rc.green = rc.blue = -1;    // white
  405.         
  406.         RGBForeColor( &rc );
  407.         OffsetRect( &itemBox, 1, 1 );
  408.         FrameRect( &itemBox );    
  409.         OffsetRect( &itemBox, -1, -1 );
  410.         
  411.         gib = itemBox;
  412.         LocalToGlobal( &topLeft( gib ));
  413.         LocalToGlobal( &botRight( gib ));
  414.  
  415.         mDev = GetMaxDevice( &gib );
  416.         
  417.         rc.red = rc.green = rc.blue = 0;    // black
  418.         GetGray( mDev, &(*(*awH)->awCTable)->ctTable[0].rgb, &rc );
  419.         
  420.         RGBForeColor( &rc );
  421.         FrameRect( &itemBox );
  422.     }
  423.     else
  424.     {
  425.         PenNormal();
  426.         PenPat( &qd.gray );
  427.         PenSize( 1,1 );
  428.         
  429.         FrameRect( &itemBox );
  430.     }
  431.     
  432.     #else
  433.     
  434.     PenNormal();
  435.     PenPat( &qd.gray );
  436.     PenSize( 1,1 );
  437.     
  438.     FrameRect( &itemBox );
  439.     
  440.     #endif
  441.     
  442.     ForeColor( blackColor );
  443.     PenNormal();
  444. }
  445.  
  446.  
  447. /*----------------------------------***  DOCUT  ***-------------------------------------*/
  448. /*    
  449. handle edit command cut.
  450. ----------------------------------------------------------------------------------------*/
  451.  
  452. void    ZDialog::DoCut()
  453. {
  454.     DialogCut( macWindow );
  455.     gClipboard->Clear();
  456.     FailOSErr( TEToScrap());
  457. }
  458.  
  459.  
  460. /*----------------------------------***  DOCOPY  ***------------------------------------*/
  461. /*    
  462. handle edit command copy.
  463. ----------------------------------------------------------------------------------------*/
  464.  
  465. void    ZDialog::DoCopy()
  466. {
  467.     DialogCopy( macWindow );
  468.     gClipboard->Clear();
  469.     FailOSErr( TEToScrap());
  470. }
  471.  
  472.  
  473. /*---------------------------------***  DOPASTE  ***------------------------------------*/
  474. /*    
  475. handle edit command paste.
  476. ----------------------------------------------------------------------------------------*/
  477.  
  478. void    ZDialog::DoPaste()
  479. {
  480.     FailOSErr( TEFromScrap());
  481.     DialogPaste( macWindow );
  482. }
  483.  
  484.  
  485. /*---------------------------------***  DOCLEAR  ***------------------------------------*/
  486. /*    
  487. handle edit command clear.
  488. ----------------------------------------------------------------------------------------*/
  489.  
  490. void    ZDialog::DoClear()
  491. {
  492.     DialogDelete( macWindow );
  493. }
  494.  
  495. /*-------------------------------***  UPDATEMENUS  ***----------------------------------*/
  496. /*    
  497. enable the edit menu items if we have edit fields
  498. ----------------------------------------------------------------------------------------*/
  499.  
  500. void    ZDialog::UpdateMenus()
  501. {
  502.     // enable cut, copy, clear IF we have edit fields. If modal,
  503.     // do NOT pass this on up the chain.
  504.     
  505.     if ( HasEditFields())
  506.     {
  507.         gMenuBar->EnableCommand( kCmdCut );
  508.         gMenuBar->EnableCommand( kCmdCopy );
  509.         gMenuBar->EnableCommand( kCmdClear );
  510.         
  511.         if ( CanPasteType())
  512.             gMenuBar->EnableCommand( kCmdPaste );
  513.     }
  514.     
  515.     if (! isModal)
  516.     {
  517.         inherited::UpdateMenus();
  518.         
  519.         // disable the save/save as menu item, since it is inappropriate for
  520.         // dialogs (ancestor window may have enabled it)
  521.         
  522.         gMenuBar->DisableCommand( kCmdSave );
  523.         gMenuBar->DisableCommand( kCmdSaveAs );
  524.     }
  525. }
  526.  
  527.  
  528. /*-------------------------------***  CANPASTETYPE  ***---------------------------------*/
  529. /*    
  530. we can paste if we have edit fields and there is text on the clipboard
  531. ----------------------------------------------------------------------------------------*/
  532.  
  533. Boolean    ZDialog::CanPasteType()
  534. {
  535.     return ( HasEditFields() && gClipboard->QueryType( 'TEXT' ));
  536. }
  537.  
  538.  
  539. /*----------------------------------***  SETUP  ***-------------------------------------*/
  540. /*    
  541.  
  542. called when the dialog is built so you can initialise your dialog items. For user items,
  543. override DrawUserItem rather than installing your own procs here. By default, this hilites
  544. the text of the first edit field it finds.
  545. ----------------------------------------------------------------------------------------*/
  546.  
  547. void    ZDialog::SetUp()
  548. {
  549.     // set the first edit field to be hilited
  550.     
  551.     short    i, iType, items = CountDITL( macWindow );
  552.     Handle    iHand;
  553.     Rect    iBox;
  554.     
  555.     for ( i = 1; i <= items; i++ )
  556.     {
  557.         GetDialogItem( macWindow, i, &iType, &iHand, &iBox );
  558.     
  559.         if (( iType & 0x7F ) == editText )
  560.         {
  561.             SelectDialogItemText( macWindow, i, 0, 32767 );
  562.             break;
  563.         }
  564.     }
  565.     // override this method to initialise your controls, etc to the desired
  566.     // state for your dialog, but call the inherited method as well.
  567. }
  568.  
  569.  
  570. /*-----------------------------***  ADJUSTCURSOR  ***-----------------------------------*/
  571. /*    
  572.  
  573. overrides ZWindow to set the cursor to an i-beam over edit fields.
  574. ----------------------------------------------------------------------------------------*/
  575.  
  576. void    ZDialog::AdjustCursor( const Point mouse, const short modifiers )
  577. {
  578.     short        item, itemType;
  579.     Handle        itemHand;
  580.     Rect        itemBox;
  581.     CursHandle    iBeam;
  582.     
  583.     item = FindItem( mouse );
  584.     
  585.     if ( item > 0 )
  586.     {
  587.         GetDialogItem( macWindow, item, &itemType, &itemHand, &itemBox );
  588.         
  589.         if (( itemType & 0x7F ) == editText )
  590.         {
  591.             iBeam = GetCursor( iBeamCursor );
  592.             SetCursor( *iBeam );
  593.             
  594.             return;
  595.         }
  596.     }
  597.     
  598.     inherited::AdjustCursor( mouse, modifiers );
  599. }
  600.  
  601.  
  602. /*--------------------------------***  CLICKITEM  ***-----------------------------------*/
  603. /*    
  604.  
  605. an enabled item was clicked (or an enabled field was typed in) This handles check boxes
  606. by toggling their state, and OK and Cancel buttons in modal dialogs. It also now handles
  607. groups of radio buttons. Override to handle clicks in other dialog items, but call the
  608. inherited method to deal with these standard items.
  609. ----------------------------------------------------------------------------------------*/
  610.  
  611. void    ZDialog::ClickItem( const short theItem )
  612. {
  613.     short    itemType;
  614.     Handle    itemHand;
  615.     Rect    itemBox;
  616.     GrafPtr    savePort;
  617.     
  618.     GetPort( &savePort );
  619.     SetPort( macWindow );
  620.     
  621.     // get info about the item clicked
  622.     
  623.     GetDialogItem( macWindow, theItem, &itemType, &itemHand, &itemBox );
  624.     
  625.     // if a checkbox, toggle its state
  626.     
  627.     if (( itemType & 0x7F ) == ( ctrlItem + chkCtrl ))
  628.         SetControlValue(( ControlHandle ) itemHand, GetControlValue(( ControlHandle ) itemHand ) ^ 1 );
  629.         
  630.     // if the item is a radio button, handle it if it is part of a group
  631.     
  632.     if (( itemType & 0x7F ) == ( ctrlItem + radCtrl ))
  633.     {
  634.         // check that the control is actually enabled
  635.         
  636.         if ((*( ControlHandle ) itemHand )->contrlHilite != 255 )
  637.             HandleRButtonGroupClick( theItem );
  638.     }
  639.     // if it is the OK or cancel button, dismiss the dialog if a modal dialog.
  640.     
  641.     if ((( theItem == ok ) || ( theItem == cancel ))    &&
  642.         (( itemType & 0x7F ) == ( ctrlItem + btnCtrl )) &&
  643.         isModal )
  644.     {
  645.         if ( theItem == ok )
  646.             Close( 1 );                // verifies dialog
  647.         else
  648.         {
  649.             dirty = FALSE;            // suppress save check
  650.             inherited::Close( 1 );    // does not verify dialog
  651.             
  652.             SendMessage( kMsgDialogCancelled, &windID );
  653.         }
  654.     }
  655.     
  656.     SetPort( savePort );
  657. }
  658.  
  659.  
  660. /*-------------------------------***  CLOSEDIALOG  ***----------------------------------*/
  661. /*    
  662.  
  663. the dialog is about to close. You can abort the close by returning FALSE. Override to
  664. read the values of controls, other items, etc.
  665. ----------------------------------------------------------------------------------------*/
  666.  
  667. Boolean    ZDialog::CloseDialog()
  668. {
  669.     // the dialog is about to close. Return FALSE if you can't close (Verify fields?)
  670.     
  671.     SendMessage( kMsgDialogSuccessfullyClosed, &windID );
  672.     
  673.     return TRUE;
  674. }
  675.  
  676.  
  677. /*----------------------------------***  CLOSE  ***-------------------------------------*/
  678. /*    
  679.  
  680. overrides ZWindow so that closing the dialog correctly maintains the chain of command.
  681. This is called when a modeless dialog is closed from the Close menu, or go-away box, or
  682. when OK was clicked in a modal dialog. 
  683. ----------------------------------------------------------------------------------------*/
  684.  
  685. Boolean    ZDialog::Close( short phase )
  686. {
  687.     // called for a modeless dialog. This calls CloseDialog. If TRUE, the object is
  688.     // deleted. This overrides the similar method in ZWindow.
  689.     
  690.     Boolean    wasClosed;
  691.     
  692.     dirty = FALSE;    // suppress save checking
  693.     
  694.     wasClosed = CloseDialog();
  695.     
  696.     if ( wasClosed )
  697.         inherited::Close( phase );
  698.         
  699.     return wasClosed;
  700. }
  701.  
  702.  
  703. /*---------------------------------***  FILTER  ***-------------------------------------*/
  704. /*    
  705.  
  706. now's your chance! This allows you to examine and modify the event that is going to come to
  707. this dialog before the dialog manager gets it. By default, this maps return and enter keys
  708. to the dialog buttons. If the event is fully handled, return TRUE, else FALSE. If TRUE is
  709. returned, no further processing will occur.
  710. ----------------------------------------------------------------------------------------*/
  711.  
  712. Boolean    ZDialog::Filter( EventRecord* theEvent )
  713. {
  714.     char        theKey;
  715.     Boolean        fullyHandled = FALSE;
  716.     short        itemType;
  717.     Handle        itemHand;
  718.     Rect        itemBox;
  719.     Boolean        cmdPeriod;
  720.     
  721.     // see if command-period is down
  722.     
  723.     cmdPeriod = ((theEvent->what == keyDown) &&
  724.                  isModal &&
  725.                  ((theEvent->modifiers & cmdKey) == cmdKey ) &&
  726.                  ((theEvent->message & charCodeMask) == '.'));
  727.     
  728.     // map return, enter and escape keys to ok and cancel
  729.     
  730.     if ((theEvent->what == keyDown) && isModal)
  731.     {
  732.         theKey = theEvent->message & charCodeMask;
  733.         
  734.         if (theKey == RETURN_KEY ||            // return
  735.             theKey == ENTER_KEY)            // enter
  736.         {
  737.             // make sure that item 1 is an enabled button
  738.             
  739.             GetDialogItem( macWindow, ok, &itemType, &itemHand, &itemBox );
  740.             
  741.             if ( itemType == ( ctrlItem + btnCtrl ))
  742.             {
  743.                 FakeClick( ok );
  744.                 fullyHandled = TRUE;
  745.             }
  746.         }
  747.         
  748.         if (( theKey == ESCAPE_KEY ) || cmdPeriod )    // escape or command-period
  749.         {
  750.             // make sure item 2 is an enabled button
  751.             
  752.             GetDialogItem( macWindow, cancel, &itemType, &itemHand, &itemBox );
  753.             
  754.             if ( itemType == ( ctrlItem + btnCtrl ))
  755.             {
  756.                 FakeClick( cancel );
  757.                 fullyHandled = TRUE;
  758.             }
  759.         }
  760.     }
  761.  
  762.     return fullyHandled;
  763. }
  764.  
  765.  
  766. /*---------------------------------***  FAKECLICK  ***----------------------------------*/
  767. /*    
  768. fake a click on an item (presumably a button).
  769. ----------------------------------------------------------------------------------------*/
  770.  
  771. void    ZDialog::FakeClick( const short item )
  772. {
  773.     long ignored;
  774.     
  775.     HiliteItem( item, 1 );
  776.     Delay( 8, &ignored );
  777.     HiliteItem( item, 0 );
  778.     
  779.     ClickItem( item );
  780. }
  781.  
  782.  
  783. /*--------------------------------***  GETITEMTYPE  ***---------------------------------*/
  784. /*    
  785. return the type of the item with ID passed.
  786. ----------------------------------------------------------------------------------------*/
  787.  
  788. short    ZDialog::GetItemType( const short item )
  789. {
  790.     short    iType;
  791.     Handle    iHand;
  792.     Rect    iRect;
  793.     
  794.     GetDialogItem( macWindow, item, &iType, &iHand, &iRect );
  795.     
  796.     return iType;
  797. }
  798.  
  799.  
  800. /*--------------------------------***  SETVALUE  ***------------------------------------*/
  801. /*    
  802.  
  803. sets the value of the dialog item to <value>. This determines the type of the item and
  804. does the obvious thing.  Various data types are accepted by overloading the parameters,
  805. though for controls, the value must be between -32767 and +32768 or an exception is thrown.
  806. ----------------------------------------------------------------------------------------*/
  807.  
  808. void    ZDialog::SetValue(const short item, const long value)
  809. {
  810.     short    itemType;
  811.     Handle    itemHand;
  812.     Rect    itemBox;
  813.     
  814.     GetDialogItem( macWindow, item, &itemType, &itemHand, &itemBox );
  815.     
  816.     // for controls: check that parameter is within range, then set the control value
  817.     
  818.     if (( itemType & ctrlItem ) == ctrlItem ) 
  819.     {
  820.         if ( value < -32767 || value > 32768 )
  821.             FailOSErr( paramErr );
  822.         else
  823.             SetControlValue(( ControlHandle ) itemHand, value );
  824.     }
  825.     else
  826.     {    
  827.         // for text items: convert long to string, and set item text
  828.         
  829.         if ( itemType & ( editText | statText ))
  830.         {
  831.             Str255    iText;
  832.             
  833.             NumToString( value, iText );
  834.             SetDialogItemText( itemHand, iText );
  835.         }
  836.     }
  837. }
  838.  
  839.  
  840. /*--------------------------------***  SETVALUE  ***------------------------------------*/
  841.  
  842. void    ZDialog::SetValue( const short item, const Str255 value )
  843. {
  844.     short    itemType;
  845.     Handle    itemHand;
  846.     Rect    itemBox;
  847.     
  848.     GetDialogItem( macWindow, item, &itemType, &itemHand, &itemBox );
  849.     
  850.     if ( itemType & ( editText | statText ))
  851.         SetDialogItemText( itemHand, value );
  852. }
  853.  
  854.  
  855. /*--------------------------------***  SETVALUE  ***------------------------------------*/
  856.  
  857. void    ZDialog::SetValue( const short item, const double value )
  858. {
  859.     short    itemType;
  860.     Handle    itemHand;
  861.     Rect    itemBox;
  862.     
  863.     GetDialogItem( macWindow, item, &itemType, &itemHand, &itemBox );
  864.     
  865.     if (( itemType & ctrlItem ) == ctrlItem )
  866.     {
  867.         SetValue( item, (long) value );
  868.     }
  869.     else
  870.     {
  871.         if ( itemType & ( editText | statText ))
  872.         {
  873.             Str255    iText;
  874.  
  875.             RealToString( value, iText );
  876.             SetDialogItemText( itemHand, iText );
  877.         }
  878.     }
  879. }
  880.  
  881. /*--------------------------------***  GETVALUE  ***------------------------------------*/
  882. /*    
  883.  
  884. gets the value of the dialog item. This determines the type of the item and
  885. does the obvious thing. For unknown items, returns 0.
  886. ----------------------------------------------------------------------------------------*/
  887.  
  888. long    ZDialog::GetValue( const short item )
  889. {
  890.     short    itemType;
  891.     Handle    itemHand;
  892.     Rect    itemBox;
  893.     
  894.     GetDialogItem( macWindow, item, &itemType, &itemHand, &itemBox );
  895.     
  896.     if (( itemType & ctrlItem ) == ctrlItem )
  897.         return GetControlValue(( ControlHandle ) itemHand );
  898.         
  899.     if (( itemType & editText ) == editText )
  900.     {
  901.         long    value;
  902.         Str255    iText;
  903.         
  904.         GetDialogItemText( itemHand, iText );
  905.         StringToNum( iText, &value );
  906.         
  907.         return value;
  908.     }
  909.     
  910.     return 0;
  911. }
  912.  
  913.  
  914. /*-----------------------------***  GETVALUEASTEXT  ***---------------------------------*/
  915. /*    
  916. get text of item, or if control, convert value to string first (complementary function to
  917. GetValue().
  918. ----------------------------------------------------------------------------------------*/
  919.  
  920. void    ZDialog::GetValueAsText( const short item, Str255 aStr )
  921. {
  922.     short    iType;
  923.     Handle    iHand;
  924.     Rect    iBox;
  925.     
  926.     GetDialogItem( macWindow, item, &iType, &iHand, &iBox );
  927.     
  928.     if ( iType & ( statText | editText ))
  929.         GetDialogItemText( iHand, aStr );
  930.     else
  931.     {
  932.         if ( iType & ctrlItem )
  933.         {
  934.             long    v = GetValue( item );
  935.         
  936.             NumToString( v, aStr );
  937.         }
  938.     }
  939. }
  940.  
  941.  
  942. float    ZDialog::GetValueAsFloat( const short item )
  943. {
  944.     Str255    itxt;
  945.     decimal    d;
  946.     short    vp, ix = 1;
  947.     
  948.     GetValueAsText( item, itxt );
  949.     
  950.     // make sure it can be read as a null-terminated string
  951.     
  952.     itxt[itxt[0] + 1 ] = 0;
  953.     
  954.     str2dec((const char*) itxt, &ix, &d, &vp);
  955.     return dec2f( &d );
  956. }
  957.  
  958.  
  959. /*-----------------------------***  GETITEMBOUNDS  ***----------------------------------*/
  960. /*    
  961. get rect of item
  962. ----------------------------------------------------------------------------------------*/
  963.  
  964. void    ZDialog::GetItemBounds( const short item, Rect* bounds )
  965. {
  966.     short    iType;
  967.     Handle    iHand;
  968.     
  969.     GetDialogItem( macWindow, item, &iType, &iHand, bounds );
  970. }
  971.  
  972.  
  973. /*--------------------------------***  FINDITEM  ***------------------------------------*/
  974. /*    
  975. find the item under the mouse point (local coordinates), 0 if no item there
  976. ----------------------------------------------------------------------------------------*/
  977.  
  978. short    ZDialog::FindItem( const Point localMouse )
  979. {
  980.     return ( FindDialogItem( macWindow, localMouse ) + 1);
  981. }
  982.  
  983.  
  984. /*------------------------------***  HILITEITEM  ***------------------------------------*/
  985. /*    
  986. allows controls to be hilited or dimmed
  987. ----------------------------------------------------------------------------------------*/
  988.  
  989. void    ZDialog::HiliteItem(const short item, const short state)
  990. {
  991.     short    itemType;
  992.     Handle    itemHand;
  993.     Rect    itemBox;
  994.     
  995.     GetDialogItem( macWindow, item, &itemType, &itemHand, &itemBox );
  996.     
  997.     if (( itemType & ctrlItem ) == ctrlItem )
  998.         HiliteControl(( ControlHandle ) itemHand, state );
  999. }
  1000.  
  1001.  
  1002. /*--------------------------***  OUTLINEDEFAULTITEM  ***--------------------------------*/
  1003. /*    
  1004. draws the bold border around the item number 1 in the dialog
  1005. ----------------------------------------------------------------------------------------*/
  1006.  
  1007. void    ZDialog::OutlineDefaultItem()
  1008. {
  1009.     short    itemType;
  1010.     Handle    itemHand;
  1011.     Rect    itemBox;
  1012.     
  1013.     GetDialogItem( macWindow, ok, &itemType, &itemHand, &itemBox );
  1014.     
  1015.     // check that this item is a button
  1016.     
  1017.     if ( itemType & ( ctrlItem + btnCtrl ))
  1018.     {
  1019.         Focus();
  1020.         PenSize( 3, 3 );
  1021.         InsetRect( &itemBox, -4, -4 );
  1022.         PenMode( patOr );
  1023.         ForeColor( blackColor );
  1024.         
  1025.         // if button disabled, draw the outline in grey (50% pat on B/W macs)
  1026.         
  1027.         if ((*(ControlHandle) itemHand)->contrlHilite != 0 )
  1028.         {
  1029.             if ( gMacInfo.supportsColour )
  1030.             {
  1031.                 RGBColor    aGray = { 0x7F7F, 0x7F7F, 0x7F7F };
  1032.                 
  1033.                 RGBForeColor( &aGray );    
  1034.             }
  1035.             else
  1036.                 PenPat( &qd.gray );
  1037.         }    
  1038.         FrameRoundRect( &itemBox, 16, 16 );
  1039.         PenNormal();
  1040.         ForeColor( blackColor );
  1041.     }    
  1042. }
  1043.  
  1044.  
  1045. /*-----------------------------***  HASEDITFIELDS  ***----------------------------------*/
  1046. /*    
  1047.  
  1048. returns TRUE if this dialog has any edit fields. Used to determine if Edit commands are
  1049. enabled or not.
  1050.  
  1051. ----------------------------------------------------------------------------------------*/
  1052.  
  1053. Boolean    ZDialog::HasEditFields()
  1054. {
  1055.     // returns TRUE if this dialog has at least one edit field. Use to enable
  1056.     // the edit menu.
  1057.  
  1058.     short    itemType, item;
  1059.     Handle    itemHand;
  1060.     Rect    itemBox;
  1061.     Boolean    hasEF = FALSE;
  1062.  
  1063.     item = CountDITL( macWindow );
  1064.     
  1065.     while(item)
  1066.     {
  1067.         GetDialogItem( macWindow, item--, &itemType, &itemHand, &itemBox );
  1068.     
  1069.         if (( itemType & 0x7F ) == editText &&
  1070.             ( itemBox.left < 16384 ))
  1071.         {
  1072.             hasEF = TRUE;
  1073.             break;
  1074.         }
  1075.     }
  1076.  
  1077.     return hasEF;
  1078. }
  1079.  
  1080.  
  1081. /*-----------------------------***  SETUPRADIOGROUPS  ***-------------------------------*/
  1082. /*    
  1083. This builds the array of radio button groups so that the click handler can correctly
  1084. manage them. This is done very easily- in your DITL resource, add the group ID to the
  1085. button title, separated by a double slash- e.g. My Button//1. This function strips the
  1086. extra characters from the name, so you never see them. Groups start at ID = 1, and
  1087. obviously buttons with the same group ID operate as a set. If you do not extend the title
  1088. of a group button in this way, it will operate in the normal way- i.e. not very well.
  1089.  
  1090. ----------------------------------------------------------------------------------------*/
  1091.  
  1092. void    ZDialog::SetUpRadioGroups()
  1093. {
  1094.     short    iType, tIndex, groupID;
  1095.     Boolean    iDefault;
  1096.     Handle    iHand;
  1097.     Rect    iBox;
  1098.     long    tSize;
  1099.     Str255    cTitle;
  1100.     
  1101.     short    iCount = CountDITL( macWindow );
  1102.  
  1103.     do
  1104.     {
  1105.         GetDialogItem( macWindow, iCount, &iType, &iHand, &iBox );
  1106.         
  1107.         // is this item a radio button?
  1108.         
  1109.         if ((iType & ( radCtrl + ctrlItem )) == ( radCtrl + ctrlItem ))
  1110.         {
  1111.             // yes, so make an entry for it in the group table. Note that all radio
  1112.             // buttons get an entry- those that do not take advantage of this scheme
  1113.             // have a groupID of zero, which instructs HandleRButtonGroupClick() to
  1114.             // ignore the button.
  1115.             
  1116.             tSize = GetHandleSize((Handle) rGroupList );
  1117.             tIndex = tSize / sizeof( RGroupEntry );
  1118.             
  1119.             SetHandleSize((Handle) rGroupList, tSize + sizeof( RGroupEntry ));
  1120.         
  1121.             // get the title of the button
  1122.             
  1123.             GetControlTitle((ControlHandle) iHand, cTitle );
  1124.             
  1125.             // parse the title looking for a double slash followed by a number. This
  1126.             // is returned in groupID, and the title is stripped of the extra chars.
  1127.             
  1128.             ParseRButtonTitle( cTitle, &groupID, &iDefault );
  1129.             
  1130.             // set up the entry in the table
  1131.             
  1132.             (*rGroupList)[tIndex].item = iCount;
  1133.             (*rGroupList)[tIndex].groupID = groupID;
  1134.             
  1135.             // set the button's name to eliminate the grouping info
  1136.             
  1137.             SetControlTitle((ControlHandle) iHand, cTitle );
  1138.             
  1139.             // if this is the default button, set it ON
  1140.             
  1141.             if ( iDefault )
  1142.                 SetControlValue((ControlHandle) iHand, 1 );
  1143.         }
  1144.     }
  1145.     while( --iCount );
  1146. }
  1147.  
  1148.  
  1149. /*---------------------------***  PARSERBUTTONTITLE  ***--------------------------------*/
  1150. /*    
  1151. Finds any group ID "buried" in the button name. This modifies the input string so that
  1152. the extra characters are removed.
  1153. ----------------------------------------------------------------------------------------*/
  1154.  
  1155. void    ZDialog::ParseRButtonTitle( Str255 buttonTitle, short* groupID, Boolean* isDefault )
  1156. {
  1157.     register char    cc = 1;
  1158.     long            gID = 0;
  1159.     Str15            subStr;
  1160.     
  1161.     *groupID = 0;        // in case we find nothing at all
  1162.     *isDefault = FALSE;
  1163.     
  1164.     // scan the string looking for two consecutive forward slashes:
  1165.     
  1166.     do
  1167.     {
  1168.         if ((buttonTitle[cc] == '/') && (buttonTitle[cc + 1] == '/'))
  1169.         {
  1170.             // found two consecutive slashes- now copy the rest of the string into
  1171.             // subStr.    
  1172.             
  1173.             subStr[0] = buttonTitle[0] - cc - 1;    // length of remainder of string
  1174.             if (subStr[0])
  1175.             {    
  1176.                 BlockMoveData(&buttonTitle[cc + 2], &subStr[1], subStr[0]);
  1177.                 
  1178.                 // look to see if this is the default button in the group. This is indicated
  1179.                 // by the ID number being followed by a '*' character.
  1180.                 
  1181.                 if ( subStr[subStr[0]] == '*' )
  1182.                 {
  1183.                     *isDefault = TRUE;
  1184.                     
  1185.                     // remove char from string
  1186.                     
  1187.                     subStr[0]--;
  1188.                 }
  1189.                 else
  1190.                     *isDefault = FALSE;
  1191.             
  1192.                 // convert substring to a number. Note that results are unpredictable if
  1193.                 // the string does not have a pure number following the two slashes.
  1194.                 // e.g. "My Button//hello" will certainly not work!
  1195.                 
  1196.                 StringToNum( subStr, &gID );
  1197.                 
  1198.                 // shorten original string by the amount needed to remove extra
  1199.                 
  1200.                 buttonTitle[0] = cc - 1;
  1201.                 *groupID = LoWord( gID );
  1202.                 
  1203.                 break;
  1204.             }    
  1205.         }
  1206.     }
  1207.     while( ++cc <= buttonTitle[0] );
  1208. }
  1209.  
  1210.  
  1211. /*------------------------***  HANDLERBUTTONGROUPCLICK  ***-----------------------------*/
  1212. /*    
  1213. turns off the buttons in the same group as this item, then turns this one on.
  1214. ----------------------------------------------------------------------------------------*/
  1215.  
  1216. void    ZDialog::HandleRButtonGroupClick(const short item)
  1217. {
  1218.     // <item> is already known to be a radio button, so find its "groupies" and turn them
  1219.     // all off. Then turn this one on.
  1220.  
  1221.     short    groupID, tIndex, gIndex, offItem;
  1222.     
  1223.     // search the group table for this item.
  1224.     // How many entries in the table?
  1225.     
  1226.     gIndex = tIndex = GetHandleSize((Handle) rGroupList) / sizeof(RGroupEntry);
  1227.     
  1228.     // for each item in the table, see if it is this item...
  1229.     
  1230.     while( tIndex )
  1231.     {
  1232.         if ((*rGroupList)[--tIndex].item == item )
  1233.         {
  1234.             // found this item- what is its group ID?
  1235.             
  1236.             groupID = (*rGroupList)[tIndex].groupID;
  1237.             
  1238.             if ( groupID != 0 )
  1239.             {
  1240.                 // found the group ID and it is not zero (meaning do not handle)
  1241.                 // now we need to find all the other items in this group and turn them off
  1242.                 
  1243.                 while( gIndex )
  1244.                 {
  1245.                     if ((*rGroupList)[--gIndex].groupID == groupID )
  1246.                     {
  1247.                         offItem = (*rGroupList)[gIndex].item;
  1248.                         SetValue( offItem, 0 );
  1249.                     }
  1250.                 }
  1251.                 
  1252.                 // now turn on the desired item
  1253.                 
  1254.                 SetValue( item, 1 );
  1255.             }
  1256.             // this item is now fully handled, so don't bother searching any further.
  1257.             
  1258.             break;
  1259.         }
  1260.     }    
  1261. }
  1262.  
  1263.  
  1264. /*-------------------------***  SETTEITEMDATAFROMICTB  ***------------------------------*/
  1265. /*    
  1266. sets the TextEdit record that is handling the item to the relevant parameters in the
  1267. associated 'ictb' resource. We made a copy of this resource when the dialog was opened.
  1268. WARNING: ensure that the item is an edit text field before calling this!
  1269. ----------------------------------------------------------------------------------------*/
  1270.  
  1271. void    ZDialog::SetTEItemDataFromIctb( const short teItem, Boolean applyChanges )
  1272. {
  1273.     if ( ictb )
  1274.     {
  1275.         // there is an ictb, so see if this item has a special entry:
  1276.         
  1277.         TEHandle        te;
  1278.         ictbItemEntry    ie;
  1279.         TextStyle        tsRec;
  1280.             
  1281.         te = ((DialogPeek) macWindow)->textH;
  1282.         ie = (*ictb)[ teItem - 1 ];
  1283.         
  1284.         if ( ie.iData != 0 &&
  1285.              ie.iOffset != 0 )
  1286.         {
  1287.             // yes, there is a special setting for this item- what is it?
  1288.             
  1289.             ictbTablePtr    tp;
  1290.             
  1291.             tp = ( ictbTablePtr ) ((Ptr) *ictb + ie.iOffset );
  1292.     
  1293.             // tp is now pointing at the text table for the item. Using this table,
  1294.             // we need to set up a TEStyle record and pass it to TextEdit.
  1295.             
  1296.             // the font is either already known or can be looked up via its name
  1297.             
  1298.             if ( ie.iData & fFamChange )
  1299.             {
  1300.                 if ( ie.iData & fIsFNameOffset )
  1301.                 {
  1302.                     // need to look up the font via the name table. In this case
  1303.                     // txtFont contains the offset to the font's name
  1304.                     
  1305.                     GetFNum((unsigned char*) *ictb + tp->txtFont , &tsRec.tsFont);
  1306.                 }
  1307.                 else
  1308.                     tsRec.tsFont = tp->txtFont;
  1309.             }
  1310.             else
  1311.                 tsRec.tsFont = 0;
  1312.                 
  1313.             // set simple fields
  1314.             
  1315.             if ( ie.iData & fFaceChange )
  1316.                 tsRec.tsFace = tp->txtFace;
  1317.             else
  1318.                 tsRec.tsFace = 0;
  1319.                 
  1320.             if ( ie.iData & fSizeChange )
  1321.                 tsRec.tsSize = tp->txtSize;
  1322.             else
  1323.                 tsRec.tsSize = 0;
  1324.                 
  1325.             // set the colours of the port
  1326.             
  1327.             if ( applyChanges )
  1328.             {
  1329.                 if ( ie.iData & fFColourChange )
  1330.                     RGBForeColor( &tp->txtFColour );
  1331.                 
  1332.                 if ( ie.iData & fBColourChange )
  1333.                     RGBBackColor( &tp->txtBColour );
  1334.             }
  1335.         }
  1336.         else
  1337.             tsRec.tsFace = tsRec.tsFont = tsRec.tsSize = 0;
  1338.         
  1339.         (*te)->txFont = tsRec.tsFont;
  1340.         (*te)->txFace = tsRec.tsFace;
  1341.         (*te)->txSize = tsRec.tsSize;
  1342.         
  1343.         // note: at this point, the lineHeight of the teRec should be calculated for the new
  1344.         // font. However, the dialog manager doesn't do this (it should). To be compatible, we
  1345.         // don't set this either. If all your fields use the same, but non-standard font, it
  1346.         // is recommended that you get the lineHeight and ascent and set up the dialog's teRec
  1347.         // correctly in the SetUp() method.    
  1348.     }
  1349. }
  1350.  
  1351.  
  1352. /*--------------------------***  ADDGREYSCALEEFFECTS  ***-------------------------------*/
  1353. /*    
  1354. adds 3D effect borders to edit text items
  1355. ----------------------------------------------------------------------------------------*/
  1356.  
  1357. void    ZDialog::AddGreyscaleEffects()
  1358. {
  1359.     short    n, iType;
  1360.     Handle    iHand;
  1361.     Rect    r;
  1362.     
  1363.     n = CountDITL( macWindow );
  1364.     
  1365.     while( n )
  1366.     {
  1367.         GetDialogItem( macWindow, n--, &iType, &iHand, &r );    
  1368.         
  1369.         if (( iType & 0x7F ) == editText )
  1370.         {
  1371.             InsetRect( &r, -3, -3 );
  1372.             FrameGrayRect( &r );
  1373.         }
  1374.     }
  1375. }
  1376.  
  1377.  
  1378. #pragma mark -
  1379. /*--------------------------***  UserItemVectorProc  ***--------------------------------*/
  1380. /*    
  1381.  
  1382. This is used to vector user-item updates to the DrawUserItem method. Do not change this-
  1383. override DrawUserItem instead.
  1384.  
  1385. ----------------------------------------------------------------------------------------*/
  1386.  
  1387. static pascal void    UserItemVectorProc( DialogPtr theDialog, short item )
  1388. {
  1389.     ZDialog*    aZD = (ZDialog*) GetWRefCon( theDialog );
  1390.     
  1391.     if ( aZD )
  1392.         aZD->DrawUserItem( item );
  1393. }
  1394.  
  1395.  
  1396. /*-------------------------------***  REALTOSTRING  ***---------------------------------*/
  1397.  
  1398. void RealToString( const double num, Str255& str )
  1399. {
  1400.     // first, stuff the integer part
  1401.     NumToString( num, str );
  1402.     // now, stuff the decimal point...
  1403.     str[++str[0]] = '.';
  1404.     // finally, stuff the stuff past the decimal...
  1405.     // since we need this to be zero-padded, we can't use NumToString here
  1406.     int v= 1000*(double)(num > 0 ? num-(int)num : (int)num - num);
  1407.     for (int i=3; i>0; i--) {
  1408.         str[str[0]+i] = '0' + v%10;
  1409.         v /= 10;
  1410.     }
  1411.     str[0] += 3;
  1412.     // add a lost negative sign -- occurs when int part is 0
  1413.     if (num < 0 && num > -1)
  1414.     {
  1415.         BlockMove( str+1, str+2, str[0] );    // shift everything over
  1416.         str[1] = '-';                        // add negative sign
  1417.         str[0]++;                            // increase string length
  1418.     }
  1419. }
  1420.  
  1421.  
  1422. /*-------------------------------***  FRAMEGRAYRECT  ***---------------------------------*/
  1423.  
  1424.  
  1425. void    FrameGrayRect( Rect* aRect )
  1426. {
  1427.     GDHandle    aDev;
  1428.     RGBColor    aColour = { -1, -1, -1 };
  1429.     RGBColor    bColour = { 0, 0, 0 };
  1430.     
  1431.     // frames a rectangle using two shades of gray so that the rectangle appears to
  1432.     // be recessed into a gray surface. This actually draws 1 pixel outside the
  1433.     // passed rectangle, so that normal FrameRect calls work as expected in addition.
  1434.     
  1435.     RGBForeColor( &aColour );
  1436.     MoveTo( aRect->left, aRect->bottom );
  1437.     LineTo( aRect->right, aRect->bottom );
  1438.     LineTo( aRect->right, aRect->top );
  1439.     
  1440.     aDev = GetMaxDevice( aRect );
  1441.     
  1442.     GetGray( aDev, &aColour, &bColour );
  1443.     RGBForeColor( &bColour );
  1444.     
  1445.     Move( 0, -1 );
  1446.     LineTo( aRect->left - 1, aRect->top - 1 );
  1447.     LineTo( aRect->left - 1, aRect->bottom );
  1448.     
  1449.     ForeColor( blackColor );
  1450. }
  1451.  
  1452.  
  1453.  
  1454.